package com.winning.gjhlht.ihe.job.thread;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.Map.Entry;
import java.util.UUID;

import org.apache.log4j.Logger;

import com.cownew.ctk.common.RandomGUID;
import com.framework.helper.ServerSQLExecutorUtils;
import com.framework.server.manager.SQLConfigLoader;
import com.framework.util.date.DateConvert;
import com.winning.common.Constans;
import com.winning.gjhlht.ihe.cdaService.service.IBaseCDACreaterServiceInter;
import com.winning.gjhlht.ihe.common.IHEConstans;

/*
 * 批量生成CDA文档线程
 */
public class IHECreateCDARequestTask extends TimerTask {


    private static Logger LOGGER = Logger.getLogger(Constans.LOG4J_PBS_LOGGER_ID);


    //判断线程是否执行完毕
    private boolean isOver = false;

    //数据源
    private String dbDataSourceID = "";

    private IBaseCDACreaterServiceInter baseCDACreaterService = null;


    //业务表数据源
    private List<Map<String, Object>> registrationRequestInfoDataList = null;

    public IHECreateCDARequestTask(List<Map<String, Object>> registrationRequestInfoDataList, IBaseCDACreaterServiceInter baseCDACreaterService, String dbDataSourceID) {
        this.registrationRequestInfoDataList = registrationRequestInfoDataList;
        this.baseCDACreaterService = baseCDACreaterService;
        this.dbDataSourceID = dbDataSourceID;
    }

    @Override
    public void run() {
        try {
            //填充所有信息, 并发送请求
            for (Iterator<Map<String, Object>> iterator = registrationRequestInfoDataList.iterator(); iterator.hasNext(); )
                if (iterator != null) {
                    //一个请求的基本信息, key值为表字段名称，统一为大写
                    Map<String, Object> map = iterator.next();

                    if (map != null) {
                        //个人基本标识号
                        String grjbbsh = (String) map.get(IHEConstans.KEY_PERSION_REGISTER_GRJBXXBSH);

                        //身份证号
                        String zjhm = (String) map.get(IHEConstans.KEY_PERSION_REGISTER_ZJHM);

                        //机构代码
                        String jgbm = (String) map.get(IHEConstans.KEY_PERSION_REGISTER_YLJGDM);

                        //国家平台唯一标识号
                        String gjptbsh = (String) map.get(IHEConstans.KEY_JBXX_REGISTER_GJPTBSH);

                        //患者姓名
                        String xm = (String) map.get(IHEConstans.KEY_PERSION_REGISTER_XM);

                        //全球唯一ID
                        //String requestID = jgbm+"_"+zjhm+"_"+ new RandomGUID().toString();
                        UUID uuid = UUID.randomUUID();
                        String uidStr = uuid.toString();
                        String[] array = uidStr.split("-");
                        String id = "";
                        for (int i = 0; i < array.length; i++) {

                            int j = Math.abs(HexToInt(array[i]));
                            String jstr = String.valueOf(j);
                            if (jstr.length() > 8) {
                                jstr = jstr.substring(0, 7) + "." + Integer.parseInt(jstr.substring(7, jstr.length()));
                            }
                            id += "." + jstr;
                        }
                        id = id.substring(1, id.length());
                        String requestID = id;

                        //LOGGER.info("-->参数  [grjbbsh="+grjbbsh+",zjhm="+zjhm+",jgbm="+jgbm+",xm="+xm+",requestID="+requestID+"]");

                        //cda模板文件名称，路径已经固定。
                        String cdaTempFileName = "cda_emr_xycf_temp";

                        String basicSQL = SQLConfigLoader.getSQLByID("IHE_QUERY_XYCF_CDA_EMR");
                        Object[] param = null;
                        //判断是否有OR
                        /*if (dbDataSourceID.indexOf(Constans.DATA_SOURCE_ORACLE_TAG) > -1) {
                            param = new Object[]{grjbbsh};
                        } else {
                            param = new Object[]{grjbbsh, grjbbsh};
                        }   */


                        //根据提供的一个患者的SQL，查询患者的健康档案信息，再根据CDA模板生成标准的CDA文档
                        HashMap<String, Object> cdaDocumentContenValue = baseCDACreaterService.createOneCDADocumentService(xm, requestID, cdaTempFileName, basicSQL, param, dbDataSourceID);

                        //生成CDA文档返回结果信息
                        //LOGGER.info("--> 返回创建CDA文档信息 ："+cdaDocumentContenValue.toString());

                        //3、将生成的CDA文档和其他基本信息保存到：CDA文档缓存表<IHE_CDA_DOC_BUFFER>
                        if (cdaDocumentContenValue != null) {

                            String cdaDocumentStr = cdaDocumentContenValue.get("cdaDocument").toString();

                            if (cdaDocumentStr == null || cdaDocumentStr.equals("")) {
                                LOGGER.info("--> 创建CDA的文档为空 ，无法写入数据库");
                                return;
                            }

                            //获取个人基本信息
                            HashMap<String, Object> jbxxMap = queryGRJBXX(grjbbsh);

                            if (jbxxMap != null) {
                                HashMap<String, Object> paramCDA = new HashMap<String, Object>();


                                paramCDA.put("Id", requestID);

                                paramCDA.put("SourcePatientID", gjptbsh);

                                paramCDA.put("SourcePatientName", xm);

                                paramCDA.put("IdentityId", zjhm);

                                //paramCDA.put("CreateTime",DateConvert.getDateYYYY_MM_DD_HH_MM_SS(new Date()));

                                paramCDA.put("UniqueId", requestID);

                                paramCDA.put("DocumentId", new RandomGUID().toString());

                                paramCDA.put("Title", "个人基本健康信息登记");
                                paramCDA.put("WDLX", "01");

                                //验证结果
                                if (cdaDocumentContenValue.containsKey("YZJG")) {
                                    paramCDA.put("YZJG", cdaDocumentContenValue.get("YZJG").toString());
                                }
                                if (cdaDocumentContenValue.containsKey("YZJGSM")) {
                                    paramCDA.put("YZJGSM", cdaDocumentContenValue.get("YZJGSM").toString());
                                }


                                LOGGER.debug("-->需要转化成Base64的CDA文档:" + cdaDocumentStr);
                                //转base64编码
                                String base64Str = getBASE64(cdaDocumentStr);
                                if (base64Str == null || base64Str.equals("")) {
                                    LOGGER.info("-->CDA文档转换Base64编码错误");
                                    return;
                                }
                                paramCDA.put("CONTENT", base64Str);
                                paramCDA.put("xmlContent", cdaDocumentStr);


                                //循环遍历查询出的个人新，并将其放入CDA缓存map中
                                for (String key : jbxxMap.keySet()) {
                                    paramCDA.put(key, jbxxMap.get(key));
                                }


                                //将cda信息保存到数据库
                                int result = saveCDADOCBUFFER(paramCDA);

                                if (result != -1) {
                                    LOGGER.info("--> CDA信息到表 IHE_CDA_DOC_BUFFER 成功");
                                } else {
                                    LOGGER.info("--> CDA信息到表 IHE_CDA_DOC_BUFFER 失败");
                                }
                            }
                        }
                    }

                }
            registrationRequestInfoDataList.removeAll(registrationRequestInfoDataList);
            registrationRequestInfoDataList = null;
        } catch (Exception e) {
            //打印异常堆栈信息
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();
        } finally {
            //线程结束状态
            isOver = true;

            System.gc();
        }

    }


    /**
     * 根据个人基本信息标识号，获取个人基本信息
     * 方法名称: queryGRJBXX
     *
     * @param
     * @return List<HashMap               <               String               ,               Object>>  返回类型说明<br/>
     * @throws <br/>
     * @author zq@winning.com.cn<br/>
     * 创建时间：2017-1-13/下午4:16:35<br/>
     */
    private HashMap<String, Object> queryGRJBXX(String grjbxxbsh) {
        try {

            String queryGRJBXXSQL = SQLConfigLoader.getSQLByID("IHE_QUERY_GRJBXX_FOR_INSERT");

            //LOGGER.info("-->查询个人信息语句SQL = " + queryGRJBXXSQL);

            List<HashMap<String, Object>> jbxxList = ServerSQLExecutorUtils.executeQueryOtherDB(queryGRJBXXSQL, new Object[]{grjbxxbsh}, dbDataSourceID);

            if (jbxxList != null) {

                return jbxxList.get(0);
            }

        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 将生产的cda信息存入数据库中
     * 方法名称: saveCDADOCBUFFER
     *
     * @param
     * @return int  返回类型说明<br/>
     * @throws <br/>
     * @author lenovo@winning.com.cn<br/>
     * 创建时间：2017-1-13/下午4:30:08<br/>
     */
    private int saveCDADOCBUFFER(HashMap<String, Object> map) {
        try {
            //拼接插入SQL语句
            //填充信息
            Object[] params = new Object[map.size()];

            String insertSQL = "INSERT INTO IHE_CDA_DOC_BUFFER (";

            //参数个数标记
            int index = 0;

            //根据个人信息map表动态填充insert语句
            for (Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();

                insertSQL += key + ",";

                params[index] = value;

                index++;

            }

//			//去除最后一个  ，符号
//			insertSQL = insertSQL.substring(0,insertSQL.length()-1);

            //添加创建时间createTime
            insertSQL += "CreateTime ";

            insertSQL += ") VALUES (";

            for (int i = 0; i < index; i++) {
                insertSQL += "?,";
            }

//			//去除最后一个  ，符号
//			insertSQL = insertSQL.substring(0,insertSQL.length()-1);

            //判断是否有OR
            if (dbDataSourceID.indexOf(Constans.DATA_SOURCE_ORACLE_TAG) > -1) {
                insertSQL += "sysdate ";
            } else {
                insertSQL += "getdate() ";
            }
            //添加创建时间createTime


            insertSQL += ")";

            LOGGER.info("-->新增SQL语句" + insertSQL);
            LOGGER.info("-->参数:" + params.toString());

            ServerSQLExecutorUtils.execute(insertSQL, params, dbDataSourceID);

            LOGGER.info("-->新增成功");

            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage());
        }

        return -1;

    }


    public boolean isOver() {
        return isOver;
    }

    /**
     * 将CDA文档内容转为BASE64格式的字符串
     * 方法名称: getBASE64
     *
     * @param cdaContentValue CDA文档中的内容
     * @return String  返回类型说明
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2017-1-12/下午4:55:25<br/>
     */
    @SuppressWarnings("restriction")
    public static String getBASE64(String cdaContentValue) {

        try {
            String base64Str = "";

            if (cdaContentValue == null) {
                return null;
            }

            try {

                base64Str = (new sun.misc.BASE64Encoder()).encode(cdaContentValue.getBytes("UTF-8")).replace("\n", "").replace("\r", "");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            return base64Str;
        } catch (Exception e) {
            LOGGER.error(e, e.fillInStackTrace());
        }

        return null;
    }


    // 16进制转10进制
    public static int HexToInt(String strHex) {
        int nResult = 0;
        if (!IsHex(strHex)) {
            return nResult;
        }
        String str = strHex.toUpperCase();
        if (str.length() > 2) {
            if (str.charAt(0) == '0' && str.charAt(1) == 'X') {
                str = str.substring(2);
            }
        }
        int nLen = str.length();
        for (int i = 0; i < nLen; ++i) {
            char ch = str.charAt(nLen - i - 1);
            try {
                nResult += (GetHex(ch) * GetPower(16, i));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return nResult;
    }

    // 判断是否是16进制数
    public static boolean IsHex(String strHex) {
        int i = 0;
        if (strHex.length() > 2) {
            if (strHex.charAt(0) == '0'
                    && (strHex.charAt(1) == 'X' || strHex.charAt(1) == 'x')) {
                i = 2;
            }
        }
        for (; i < strHex.length(); ++i) {
            char ch = strHex.charAt(i);
            if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')
                    || (ch >= 'a' && ch <= 'f')) {
                continue;
            }
            return false;
        }
        return true;
    }

    // 计算16进制对应的数值
    public static int GetHex(char ch) throws Exception {
        if (ch >= '0' && ch <= '9')
            return (int) (ch - '0');
        if (ch >= 'a' && ch <= 'f')
            return (int) (ch - 'a' + 10);
        if (ch >= 'A' && ch <= 'F')
            return (int) (ch - 'A' + 10);
        throw new Exception("error param");
    }

    // 计算幂
    public static int GetPower(int nValue, int nCount) throws Exception {
        if (nCount < 0) {
            throw new Exception("nCount can't small than 1!");
        }
        if (nCount == 0) {
            return 1;
        }
        int nSum = 1;
        for (int i = 0; i < nCount; ++i) {
            nSum = nSum * nValue;
        }
        return nSum;
    }


}
